package com.scalar.chiptrack.workflow;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Map;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.event.CellEditorListener;

import com.jgraph.graph.CellView;
import com.jgraph.graph.DefaultEdge;
import com.jgraph.graph.DefaultGraphCell;
import com.jgraph.graph.DefaultPort;
import com.jgraph.graph.GraphCellEditor;
import com.jgraph.graph.GraphConstants;
import com.jgraph.plaf.basic.BasicGraphUI;

public class WorkflowGraphUI extends BasicGraphUI 
{
	protected CellEditorListener cellEditorListener;

	protected JFrame editDialog = null;
		
	public WorkflowGraph getGraph()
	{
		return (WorkflowGraph)graph;
	}
	
	/** 
	* Create the dialog using the cell's editing component. 
	*/
	protected void createEditDialog( Object cell, MouseEvent event ) 
	{
		if( cell instanceof DefaultGraphCell )
		{
			if( !( cell instanceof DefaultEdge ) )
			{

                Map map = ((DefaultGraphCell)cell).getAttributes();
                int firstStrongIndex    = -1;
                int lastStrongIndex     = -1;
                String tempValue = (String)map.get("value");
                if ( tempValue != null && ((String)tempValue).length() > 0 && ((String)tempValue).indexOf("<STRONG>") > 0 && ((String)tempValue).indexOf("</STRONG>") > 0 )
                {
                    firstStrongIndex = ((String)tempValue).indexOf("<STRONG>") + "<STRONG>".length();
                    lastStrongIndex  = ((String)tempValue).indexOf("</STRONG>");
                    if ( firstStrongIndex != -1 && lastStrongIndex != -1 )
                    {
                        tempValue = ((String)tempValue).substring(firstStrongIndex, lastStrongIndex);
                    }
                }
                map.put("value", tempValue);
				Dimension editorSize = editingComponent.getPreferredSize();
				//editDialog = new JFrame("Edit " + getGraph().convertValueToString(cell));
                editDialog = new JFrame("Edit " + tempValue);
				//editDialog.setSize(editorSize.width, editorSize.height);
				editDialog.setSize( 400, 200 );
				//editDialog.getContentPane().add(editingComponent);
				editDialog.getContentPane().add( new PopupPanel( editDialog, editingComponent, cell, getGraph() ) );
				editingComponent.validate();
				editDialog.pack();
				//editDialog.show();
                editDialog.setVisible(true);
			}
			else
			{
				editDialog = new JFrame( "Transport Information "  + getGraph().convertValueToString(cell) );
				editDialog.setSize( 400, 200 );
				DefaultEdge edge = ( DefaultEdge )cell;
				DefaultGraphCell sourceCell = null;
				DefaultGraphCell targetCell = null;
				
				if( edge.getSource() != null )
				{
					sourceCell = (DefaultGraphCell)((DefaultPort)edge.getSource()).getParent();
				}

				if( edge.getTarget() != null )
				{
					targetCell = (DefaultGraphCell)((DefaultPort)edge.getTarget()).getParent();
				}

                Map sourceAttributes = sourceCell.getAttributes();
                Map activityAttributesMap = null;
                if ( sourceAttributes.containsKey( "processStepId" ) && sourceAttributes.get( "processStepId" ) != null && ( (String)sourceAttributes.get( "processStepId" ) ).length() > 0 )
                {
                    activityAttributesMap = PopupPanel.getActivityAttributesMap( (String)sourceAttributes.get( "processStepId" ), getGraph() );
                }
                if ( activityAttributesMap != null )
                {
                    sourceAttributes.putAll( activityAttributesMap );
                }
                Map targetAttributes = targetCell.getAttributes();
                if ( targetAttributes.containsKey( "processStepId" ) && targetAttributes.get( "processStepId" ) != null && ( (String)targetAttributes.get( "processStepId" ) ).length() > 0 )
                {
                    activityAttributesMap = PopupPanel.getActivityAttributesMap( (String)targetAttributes.get( "processStepId" ), getGraph() );
                }
                if ( activityAttributesMap != null )
                {
                    targetAttributes.putAll( activityAttributesMap );
                }
                String error = "" ;
				
				if( sourceAttributes.get( "Type" ) == null ) 
				{  
					if ( targetAttributes.get( "Type" ) == null )
				 	{   
				 		error = "Source and Target Process not Yet Configured"; 
				 	}          
					else
					{   
						error = "Source Process not yet Configured ";   
					}
				}				
				else if( targetAttributes.get( "Type" ) == null )  
				{ 
					error = "Target Process not yet configuired ";		
				}
				else
				{
					String sourceVendorLocations = (String) sourceAttributes.get( "vendors" );
					String targetVendorLocations = (String) targetAttributes.get( "vendors" );
					ArrayList sourceVendors		 = parseString( sourceVendorLocations, '#' );
					ArrayList targetVendors		 = parseString( targetVendorLocations, '#' );
					
					if( sourceVendors.size() < 1 )
					{
						error = "No Vendors selected for Source Process";
					}
					else if ( targetVendors.size() < 1 )
					{
						error = "No Vendors selected for Target Process";
					}
					else if ( sourceVendors.size() == 1 && targetVendors.size() == 1 )
					{
						ArrayList sourceLocation = parseString( (String)sourceVendors.get( 0 ), ';' );
						ArrayList targetLocation = parseString( (String)targetVendors.get( 0 ), ';' );
						String source = null;
						String target = null;
						
						if( sourceLocation.size() > 2 )
						{
							source = (String)sourceLocation.get( 2 ); 
						}

						if( targetLocation.size() > 2 )
						{
							target = (String)targetLocation.get( 2 ); 
						}
						if( source != null && target != null && source.equalsIgnoreCase( target ) )
						{
							error = "Source and Vendor locations are the same";
						}
					}
				}
			  	
			  	if ( error.length() > 1 )
			   	{  
					JOptionPane.showMessageDialog( editDialog, error, "Chiptrac Error", JOptionPane.ERROR_MESSAGE );
			   	}
			   	else
				{ 
					editDialog.getContentPane().add( new PopupPanel( editDialog, editingComponent, cell, sourceCell, targetCell, getGraph() ) );
					editingComponent.validate();
					editDialog.pack();
					//editDialog.show();
					editDialog.setVisible(true);
				}
				/*editDialog.getContentPane().add( new PopupPanel( editDialog, editingComponent, cell, sourceCell, targetCell, getGraph() ) );
				editingComponent.validate();
				editDialog.pack();
				editDialog.show();*/
			}
		}	
	}
		
		/*protected MouseListener createMouseListener(){
			return new WorkflowMouseHandler();
		}
		
		public class WorkflowMouseHandler extends MouseHandler{
			public void mousePressed(MouseEvent ev){
				System.out.println("This is check in a cell");
			}
		}*/
		
		public void paintCell( Graphics g, CellView view, Rectangle bounds, boolean preview )
		{
			super.paintCell( g, view, bounds, preview );
			//System.out.println( "bounds Cell   " + bounds.getX() + bounds.getY() );		   
		}	
		
    /** 
	* Stops the editing session. If messageStop is true the editor 
	* is messaged with stopEditing, if messageCancel is true the 
	* editor is messaged with cancelEditing. If messageGraph is true 
	* the graphModel is messaged with valueForCellChanged. 
	*/
	protected void completeEditing(	boolean messageStop, boolean messageCancel,	boolean messageGraph) 
	{
		if ( stopEditingInCompleteEditing && editingComponent != null && editDialog != null ) 
		{
			Component oldComponent 	= editingComponent;
			Object oldCell 			= editingCell;
			GraphCellEditor oldEditor = cellEditor;

			//Object newValue = oldEditor.getCellEditorValue();
            StringBuffer sb = new StringBuffer(50);
            sb.append("<html>");
            sb.append("<body align='center'><font face='Arial' size='2'>");
            sb.append("<STRONG>" + ((String)((DefaultGraphCell)oldCell).getAttributes().get("value")) + "</STRONG>"+ "<BR>" + "<STRONG>" + ((String)((DefaultGraphCell)oldCell).getAttributes().get("partnumber")) + "</STRONG>" );
            sb.append("</body>");
            sb.append("</html>");
            Object newValue = sb.toString();
            //Object newValue = ((String)((DefaultGraphCell)oldCell).getAttributes().get("value"))+ "/" + ((String)((DefaultGraphCell)oldCell).getAttributes().get("partnumber"));
			//Object newValue = (((DefaultGraphCell)oldCell).getAttributes().get("value"));
			// This if condition is placed because ..
			// When we place two Cells and a transition between them. When we click one popup Panel and Click cancel
			// Again click on tracsition and Cancel .. now click on Cell it is giving a null Pointer 
			if( newValue != null )
			{
                if( ((DefaultGraphCell)oldCell).getAttributes().get("value") != null && !((DefaultGraphCell)oldCell).getAttributes().get("value").equals( oldEditor.getCellEditorValue() ) )
                {
                    messageGraph = true;
                }
            }
			Rectangle editingBounds = getGraph().getCellBounds( editingCell );
			
			boolean requestFocus =	(graph != null	&& (graph.hasFocus() || editingComponent.hasFocus()));
			
			editingCell = null;
			
			editingComponent = null;
			
			if (messageStop)
				oldEditor.stopCellEditing();
			else if (messageCancel)
			{
				oldEditor.cancelCellEditing();	
			}
			
			editDialog.dispose();
			
			if (requestFocus)
				graph.requestFocus();
			
			if ( messageGraph ) 
			{
				Map map = GraphConstants.createMap();
				GraphConstants.setValue(map, newValue);
				Map nested = new Hashtable();
				nested.put(oldCell, map);
				graphLayoutCache.edit(nested, null, null, null);
			}
			
			updateSize();
			
			// Remove Editor Listener 
			if ( oldEditor != null && cellEditorListener != null )
				oldEditor.removeCellEditorListener(cellEditorListener);

			cellEditor = null;
			editDialog = null;
		}
	}

	/** 
	* Will start editing for cell if there is a cellEditor and 
	* shouldSelectCell returns true.<p> 
	* This assumes that cell is valid and visible. 
	*/
	protected boolean startEditing(Object cell, MouseEvent event) 
	{
		completeEditing();
		if (getGraph().isCellEditable(cell) && editDialog == null) 
		{
			// Create Editing Component **** ***** 
			CellView tmp = graphLayoutCache.getMapping(cell, false);
			cellEditor = tmp.getEditor();
			editingComponent = cellEditor.getGraphCellEditorComponent(getGraph(), cell, graph.isCellSelected(cell));
			if (cellEditor.isCellEditable(event)) 
			{
				editingCell = cell;
				// Create Wrapper Dialog **** ***** 
				if(!getGraph().getEditor().isGroup(cell))
				{
					createEditDialog(cell, event);
				}
					
				// Add Editor Listener 
				if (cellEditorListener == null)
					cellEditorListener = createCellEditorListener();
				if (cellEditor != null && cellEditorListener != null)
					cellEditor.addCellEditorListener(cellEditorListener);
				if (cellEditor.shouldSelectCell(event)) 
				{
					stopEditingInCompleteEditing = false;
					try 
					{
						getGraph().setSelectionCell(cell);
					} 
					catch (Exception e) 
					{
						System.err.println("Editing exception: " + e);
					}
					stopEditingInCompleteEditing = true;
				}
				
				if (event instanceof MouseEvent) 
				{
					/// Find the component that will get forwarded all the 
					//mouse events until mouseReleased. 
					Point componentPoint = SwingUtilities.convertPoint(	getGraph(),	new Point(event.getX(), event.getY()),editingComponent);
					// Create an instance of BasicTreeMouseListener to handle 
					//passing the mouse/motion events to the necessary 
					//component. 
					// We really want similiar behavior to getMouseEventTarget, 
					// but it is package private. 
					Component activeComponent =	SwingUtilities.getDeepestComponentAt( editingComponent,	componentPoint.x,componentPoint.y);
					if (activeComponent != null) 
					{
						new MouseInputHandler(getGraph(),activeComponent,event);
					}
				}
				return true;
			} 
			else
				editingComponent = null;
		}
		return false;
	}
	
	public ArrayList parseString( String string, char delim )
	{
		char[] charArray	= string.toCharArray();
		ArrayList list 		= new ArrayList();
		StringBuffer sb 	= new StringBuffer();
		
		for( int i = 0; i < charArray.length; i++ )
		{
			if( charArray[i] != delim )
			{
				sb.append( charArray[i] );
			}
			else
			{
				list.add( sb.toString().trim() );
				sb.delete( 0, sb.length() );
			}
		}
		if( sb.length() > 0 )
			list.add( sb.toString().trim() );
		return list;
	}
}